/*
 * @(#)XfsimConfig.java        2003/01/01
 *
 * This file is part of Xfuzzy 3.0, a design environment for fuzzy logic
 * based systems.
 *
 * (c) 2000 IMSE-CNM. The authors may be contacted by the email address:
 *                    xfuzzy-team@imse.cnm.es
 *
 * Xfuzzy is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation.
 *
 * Xfuzzy is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 */

package xfuzzy.xfsim.model;

import xfuzzy.*;
import xfuzzy.lang.*;
import java.io.*;
import java.util.*;
import java.net.*;

/**
 * Clase que contiene la configuraci�n de un proceso de simulaci�n
 * 
 * @author Francisco Jos� Moreno Velo
 *
 */
public class XfsimConfig  {
	
	//----------------------------------------------------------------------------//
	//                            MIEMBROS PRIVADOS                               //
	//----------------------------------------------------------------------------//
		
	/**
	 * Fichero ".class" que describe el modelo de planta
	 */
	private File plantfile;
	
	/**
	 * Clase instanciada del modelo de planta
	 */
	private PlantModel plant;
	
	/**
	 * Valores iniciales de la planta
	 */
	private double[] init;
	
	/**
	 * Condiciones de finalizaci�n de la simulaci�n
	 */
	private XfsimLimit limit;
	
	/**
	 * Lista de salidas de la simulaci�n
	 */
	private Vector<XfsimOutput> output;
	
	//----------------------------------------------------------------------------//
	//                                CONSTRUCTOR                                 //
	//----------------------------------------------------------------------------//

	/**
	 * Constructor
	 */
	public XfsimConfig() {
		this.limit = new XfsimLimit(0,0);
		this.output = new Vector<XfsimOutput>();
	}
	
	//----------------------------------------------------------------------------//
	//                             M�TODOS P�BLICOS                               //
	//----------------------------------------------------------------------------//
		
	/**
	 * Verifica que la configuraci�n est� completa	
	 */
	public boolean isConfigured() {
		if(plant == null || !limit.isConfigured()) return false;
		return true;
	}
	
	/**
	 * Obtiene el fichero que describe el modelo de planta
	 * @return
	 */
	public File getPlantFile() {
		return this.plantfile;
	}
	
	/**
	 * Selecciona el fichero que contiene el modelo de planta
	 */
	public void setPlantModel(File file) throws XflException {
		try {
			URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
			URL url = sysloader.findResource(file.getParentFile().getAbsolutePath());
			URL[] urls = new URL[1];
			urls[0] = url;
			URLClassLoader loader = URLClassLoader.newInstance(urls);
			String classname = file.getName().replaceFirst(".class", "");
			Class<?> pclass = loader.loadClass(classname);
			plant = (PlantModel) pclass.newInstance();
			plantfile = file;
		} catch(Exception e) { 
			throw new XflException(32); 
		}
	}
	
	/**
	 * Obtiene la referencia a la planta
	 * @return
	 */
	public PlantModel getPlantModel() {
		return this.plant;
	}
	
	
	/**
	 * Asigna los valores iniciales de la planta
	 * @param init
	 */
	public void setPlantInit(double[] init) {
		this.init = init;
	}
	
	/**
	 * Obtiene los valores iniciales de la planta
	 * @return
	 */
	public double[] getPlantInit() {
		return this.init;
	}

	/**
	 * Asigna un valor de inicializaci�n de la planta
	 * @param var
	 * @param value
	 */
	public void setPlantInit(String var, String value) {
		int index = Integer.parseInt(var.substring(1));
		double val = Double.parseDouble(value);
		if(this.init == null) {
			this.init = new double[index+1];
			this.init[index] = val;
		} else if(init.length <= index ) {
			double[] aux = new double[index+1];
			System.arraycopy(init, 0, aux, 0, init.length);
			aux[index] = val;
			this.init = aux;
		} else {
			this.init[index] = val;
		}	
	}
	
	/**
	 * Asigna las condiciones de finalizaci�n de la simulaci�n
	 * @param limit
	 */
	public void setLimit(XfsimLimit limit) {
		this.limit = limit;
	}

	/**
	 * Obtiene las condiciones de finalizaci�n de la simulaci�n

	 * @return
	 */
	public XfsimLimit getLimit() {
		return this.limit;
	}
	
	/**
	 * A�ade una salida a la configuraci�n
	 * @param no
	 */
	public void addOutput(XfsimOutput no) {
		this.output.add(no);
	}
	
	/**
	 * Elimina una salida de la configuraci�n
	 * @param ro
	 */
	public void removeOutput(XfsimOutput ro) {
		this.output.remove(ro);
	}
	
	/**
	 * Obtiene la lista de salidas del procseo de simulaci�n
	 * @return
	 */
	public XfsimOutput[] getOutputs() {
		int size = output.size();
		XfsimOutput[] array = new XfsimOutput[size];
		for(int i=0; i<size; i++) array[i] = output.elementAt(i);
		return array;
	}
	
	/**
	 * Representaci�n en formato XML
	 */
	public String toXML(String sysname) {
		String eol = System.getProperty("line.separator", "\n");
		String code = "<xfuzzy>"+eol; 
		code += "\t<xfsim system=\""+sysname+"\">"+eol;
		if(plantfile != null) {
			code += "\t\t<plant file=\""+plantfile.getAbsolutePath()+"\"></plant>"+eol;			
		}
		if(init != null && init.length != 0) {
			code += "\t\t<init>"+eol;
			for(int i=0; i<init.length; i++) {
				code += "\t\t\t<var name=\"i"+i+"\" value=\""+init[i]+"\"></var>"+eol;
			}
			code += "\t\t</init>"+eol;
		}
		code += limit.toXML();
		for(int i=0; i<output.size(); i++) {
			code += output.elementAt(i).toXML();
		}
		
		code += "\t</xfsim>"+eol;
		code += "</xfuzzy>"+eol;
		return code;
	}

	/**
	 * Almacenar la configuracion en un fichero
	 */
	public boolean save(File file,String sysname, boolean append) {
		String code = toXML(sysname);
		byte buf[] = code.getBytes();

		try {
			OutputStream stream = new FileOutputStream(file,append);
			stream.write(buf);
			stream.close();
		}
		catch (IOException e) { return false; }
		return true;
	}
}
